package com.example.common.recycler.viewbinding;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.viewbinding.ViewBinding;

import com.example.common.recycler.base.BaseRecyclerAdapter;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

/**
 * 此类适用于单一数据类型的RecyclerView
 * 使用时只需继承此类，然后实现抽象方法即可
 * 如果是多数据类型的，请使用BaseViewBindingRecyclerAdapter
 * 注意：
 * 请务必在混淆中增加如下已保证inflate方法不被混淆：
 * -keepclasseswithmembers class **.databinding.** {
 * public static ** inflate(**);
 * }
 *
 * @param <T>  与视图对应的实体类
 * @param <VB> 与视图对应的ViewBinding
 */
public abstract class BaseSingleViewBindingRecyclerAdapter<T, VB extends ViewBinding> extends BaseRecyclerAdapter<T, ViewBindingViewHolder<VB>> {
    public Type viewBindingType; //存放泛型VB的实际类型

    public BaseSingleViewBindingRecyclerAdapter() {
        viewBindingType = getViewBindingType(getClass());
    }

    /**
     * 获得泛型VB的实际类型
     *
     * @param subclass
     * @return
     */
    public Type getViewBindingType(Class<?> subclass) {
        Type superclass = subclass.getGenericSuperclass();
        if (superclass instanceof Class) {
            throw new RuntimeException("Missing type parameter.");
        }
        ParameterizedType parameterized = (ParameterizedType) superclass;
        return parameterized.getActualTypeArguments()[1];
    }

    /**
     * 设置控件的显示内容
     *
     * @param holder
     * @param t
     */
    public abstract void onBindView(@NonNull ViewBindingViewHolder<VB> holder, int position, T t, @NonNull List<Object> payloads);

    @NonNull
    @Override
    public ViewBindingViewHolder<VB> onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
//        Log.i("123456", "mViewBindingType=" + mViewBindingType);
        VB result = null;
        try {
            //由于以下使用到反射，因此反射方法必须不能被混淆
            Class cls = (Class) viewBindingType;
            Method bindMethod = cls.getMethod("inflate", LayoutInflater.class, ViewGroup.class, boolean.class);
            result = (VB) bindMethod.invoke(null, LayoutInflater.from(parent.getContext()), parent, false);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("发生错误：" + e.getMessage() + ",请确保填写的泛型（" + viewBindingType + "）无误或者在混淆中配置使得自动生成的databinding类的inflate方法不被混淆：\n-keepclasseswithmembers class **.databinding.** {\n" +
                    "    public static ** inflate(android.view.LayoutInflater,android.view.ViewGroup,boolean);\n" +
                    "}");
        }
        return new ViewBindingViewHolder(result);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewBindingViewHolder<VB> holder, int position, @NonNull List<Object> payloads) {
        super.onBindViewHolder(holder, position, payloads);
        onBindView(holder, position, getItem(position), payloads);
    }
}